home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / hoster / pvmwinhoster.c < prev    next >
C/C++ Source or Header  |  1997-07-22  |  17KB  |  783 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: pvmwinhoster.c,v 1.2 1997/07/09 13:28:48 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /*
  34. *    pvmwin_hoster.c
  35. *
  36. *    acts like pvmd' uses rexec right now.
  37. *    will get rsh for WIN95 soon
  38. *    
  39. *    /9/24/1996 Markus Fischer
  40. */
  41.  
  42. #ifdef WIN32
  43. #include "..\src\pvmwin.h"
  44. #include <pvmproto.h>
  45. #endif
  46.  
  47. #ifndef RSHCOMMAND
  48. #define RSHCOMMAND      "/usr/ucb/rsh"
  49. #endif
  50.  
  51. #ifdef HASSTDLIB
  52. #include <stdlib.h>
  53. #endif
  54. #include <stdlib.h>
  55. #include <stdio.h>
  56. #include <sys/types.h>
  57. #include <errno.h>
  58. #ifndef WIN32
  59. #include <pwd.h>
  60. #include <netdb.h>
  61. #endif
  62. #ifdef    SYSVSTR
  63. #include <string.h>
  64. #define    CINDEX(s,c)    strchr(s,c)
  65. #else
  66. #include <strings.h>
  67. #define    CINDEX(s,c)    index(s,c)
  68. #endif
  69. #include "../include/pvm3.h"
  70. #include "../include/pvmsdpro.h"
  71.  
  72.  
  73. /* if > 1, uses parallel startup strategy */
  74.  
  75.  
  76. #ifndef    RSHNPLL
  77.  
  78. #define    RSHNPLL    5
  79. #endif
  80.  
  81. #ifndef RSHTIMEOUT
  82. #define RSHTIMEOUT 100
  83. #endif
  84.  
  85. #ifndef    max
  86. #define    max(a,b)    ((a)>(b)?(a):(b))
  87. #endif
  88.  
  89. #ifndef    min
  90. #define    min(a,b)    ((a)<(b)?(a):(b))
  91. #endif
  92.  
  93. #define    TALLOC(n,t,g)    (t*)malloc((n)*sizeof(t))
  94. #define    FREE(p)    free((char *)p)
  95. #define    STRALLOC(s)            strcpy(TALLOC(strlen(s)+1,char,"str"),s)
  96.  
  97. #define    LISTPUTAFTER(o,n,f,r) \
  98.     { (n)->f=(o)->f; (n)->r=o; (o)->f->r=n; (o)->f=n; }
  99. #define    LISTPUTBEFORE(o,n,f,r) \
  100.     { (n)->r=(o)->r; (n)->f=o; (o)->r->f=n; (o)->r=n; }
  101. #define    LISTDELETE(e,f,r) \
  102.     { (e)->f->r=(e)->r; (e)->r->f=(e)->f; (e)->r=(e)->f=0; }
  103.  
  104. #define    TVCLEAR(tvp)    ((tvp)->tv_sec = (tvp)->tv_usec = 0)
  105.  
  106. #define    TVISSET(tvp)    ((tvp)->tv_sec || (tvp)->tv_usec)
  107.  
  108. #define    TVXLTY(xtv, ytv) \
  109.     ((xtv)->tv_sec < (ytv)->tv_sec || \
  110.         ((xtv)->tv_sec == (ytv)->tv_sec && (xtv)->tv_usec < (ytv)->tv_usec))
  111.  
  112. #define    TVXADDY(ztv, xtv, ytv)    \
  113.     if (((ztv)->tv_usec = (xtv)->tv_usec + (ytv)->tv_usec) < 1000000) {    \
  114.         (ztv)->tv_sec = (xtv)->tv_sec + (ytv)->tv_sec;    \
  115.     } else {    \
  116.         (ztv)->tv_usec -= 1000000;    \
  117.         (ztv)->tv_sec = (xtv)->tv_sec + (ytv)->tv_sec + 1;    \
  118.     }
  119.  
  120. #define    TVXSUBY(ztv, xtv, ytv)    \
  121.     if ((xtv)->tv_usec >= (ytv)->tv_usec) {    \
  122.         (ztv)->tv_sec = (xtv)->tv_sec - (ytv)->tv_sec;    \
  123.         (ztv)->tv_usec = (xtv)->tv_usec - (ytv)->tv_usec;    \
  124.     } else {    \
  125.         (ztv)->tv_sec = (xtv)->tv_sec - (ytv)->tv_sec - 1;    \
  126.         (ztv)->tv_usec = (xtv)->tv_usec + 1000000 - (ytv)->tv_usec;    \
  127.     }
  128.  
  129. /*
  130. *    for keeping state assoc. with a host
  131. */
  132.  
  133. struct hst {
  134.     int h_tid;
  135.     char *h_name;
  136.     char *h_login;
  137.     char *h_sopts;
  138.     int h_flag;
  139. #define    HST_PASSWORD    1        /* ask for a password */
  140. #define    HST_MANUAL        2        /* do manual startup */
  141.     char *h_cmd;
  142.     char *h_result;
  143. };
  144.  
  145. static char pvmtxt[1024];        /* scratch for error log */
  146.  
  147.  
  148. int debugmask = 0;
  149. extern char* username;
  150. char *getenv();
  151.  
  152. int main (argc, argv)
  153.     int argc;
  154.     char **argv;
  155. {
  156.  
  157.     static int init=0;
  158.     static int needed=1;
  159.  
  160.     // DebugBreak();    
  161.  
  162.    
  163.     pvm_mytid();
  164.     pvm_reg_hoster();
  165.     pvm_setopt(PvmResvTids, 1);
  166.  
  167.  
  168.     
  169.     while (pvm_recv(-1, SM_STHOST) > 0) {
  170.         AllocConsole();
  171.         
  172.         GetStdHandle(STD_OUTPUT_HANDLE);
  173.         if (init)  
  174.             printf("***need more ?                                         ***\n");
  175.  
  176.         hoster();
  177.         if (!init) { 
  178.             printf("*** PVM pvmd starter                                   ***\n");
  179.             printf("*** Here you can see what your 'add command' is doing  ***\n");
  180.             printf("*** Also, if you are required to type in passwords :-( ***\n");
  181.             printf("*** this is the right place :-)                        ***\n");
  182.             printf("*** It will pop up the next time you have to add more  ***\n");
  183.             printf("*** slaves and will vanish therefore ...               ***\n");
  184.             Sleep(12000);    
  185.             printf("*** Now ! ..... later ...                              ***\n");
  186.             Sleep(1000);
  187.             FreeConsole();
  188.             init=1;
  189.         }
  190.     
  191.         
  192.     } 
  193.     pvm_exit();
  194.     exit(0);
  195.     
  196.     return 0;
  197. }
  198.  
  199.  
  200. /*    hoster()
  201. *
  202. *    Unpack host table from message, attempt to start 'em up,
  203. *    send reply message.
  204. */
  205.  
  206. hoster()
  207. {
  208.     int num;
  209.     int i;
  210.     struct hst **hostlist;
  211.     struct hst *hp;
  212.     char *p;
  213.     char sopts[64];
  214.     char lognam[256];
  215.     char cmd[512];
  216.     int fromtid;
  217.     int wid;
  218.  
  219.     /*
  220.     * unpack the startup message
  221.     */
  222.  
  223.     pvm_bufinfo(pvm_getrbuf(), (int *)0, (int *)0, &fromtid);
  224.     pvm_unpackf("%d", &num);
  225.     wid = pvm_getmwid(pvm_getrbuf());
  226.     printf("hoster() %d to start, wait id %d\n", num, wid);
  227.     fflush(stdout);
  228.     if (num > 0) {
  229.         hostlist = TALLOC(num, struct hst *, "xxx");
  230.         for (i = 0; i < num; i++) {
  231.             hp = TALLOC(1, struct hst, "xxx");
  232.             hostlist[i] = hp;
  233.             hp->h_flag = 0;
  234.             hp->h_result = 0;
  235.             if (pvm_unpackf("%d %s %s %s", &hp->h_tid, sopts, lognam, cmd)) {
  236.                 printf("hoster() bad message format\n");
  237.                 pvm_exit();
  238.                 exit(1);
  239.             }
  240.             hp->h_sopts = STRALLOC(sopts);
  241.             hp->h_login = STRALLOC(lognam);
  242.             hp->h_cmd = STRALLOC(cmd);
  243.             printf("%d. t%x %s so=\"%s\"\n", i,
  244.                     hp->h_tid,
  245.                     hp->h_login,
  246.                     hp->h_sopts);
  247.             if (p = CINDEX(hp->h_login, '@')) {
  248.                 hp->h_name = STRALLOC(p + 1);
  249.                 *p = 0;
  250.                 p = STRALLOC(hp->h_login);
  251.                 FREE(hp->h_login);
  252.                 hp->h_login = p;
  253.  
  254.             } else {
  255.                 hp->h_name = hp->h_login;
  256.                 hp->h_login = 0;
  257.             }
  258.             if (!strcmp(hp->h_sopts, "pw"))
  259.                 hp->h_flag |= HST_PASSWORD;
  260.             if (!strcmp(hp->h_sopts, "ms"))
  261.                 hp->h_flag |= HST_MANUAL;
  262.         }
  263.     }
  264.  
  265.     /*
  266.     * do it
  267.     */
  268.  
  269. #if    RSHNPLL > 1
  270.     pl_startup(num, hostlist);
  271.  
  272. #else    /*RSHNPLL > 1*/
  273.     for (i = 0; i < num; i++)
  274.         pl_startup(1,hostlist++);
  275.  
  276. #endif    /*RSHNPLL > 1*/
  277.  
  278.     /*
  279.     * send results back to pvmd
  280.     */
  281.  
  282.     pvm_packf("%+ %d", PvmDataFoo, num);
  283.     for (i = 0; i < num; i++) {
  284.         pvm_packf("%d", hostlist[i]->h_tid);
  285.         pvm_packf("%s", hostlist[i]->h_result
  286.                 ? hostlist[i]->h_result : "PvmDSysErr");
  287.     }
  288.  
  289. /*
  290.     printf("hoster() sending back host table\n");
  291. */
  292.     pvm_setmwid(pvm_getsbuf(), wid);
  293.     pvm_send(fromtid, SM_STHOSTACK);
  294.  
  295.     return 0;
  296. }
  297.  
  298.  
  299. #if RSHNPLL > 1
  300.  
  301. /********************************************
  302. *  this is the new (parallel) startup code  *
  303. *                                           *
  304. ********************************************/
  305.  
  306. struct slot {
  307.     struct slot *s_link, *s_rlink;        /* free/active list */
  308.     struct hst *s_hst;                    /* host table entry */
  309.     struct timeval s_bail;                /* timeout time */
  310.     int s_rfd, s_wfd, s_efd;            /* slave stdin/out/err */
  311.     char s_buf[256];                    /* config reply line */
  312.     int s_len;                            /* length of s_buf */
  313. };
  314.  
  315.  
  316. static struct slot slots[RSHNPLL+2];    /* state var/context for each slot */
  317. static struct slot *slfree = 0;            /* free list of slots */
  318.  
  319. close_slot(sp)
  320.     struct slot *sp;
  321. {
  322.     if (sp->s_wfd != -1)
  323.         (void)_close(sp->s_wfd);
  324.     if (sp->s_rfd != -1)
  325.         (void)_close(sp->s_rfd);
  326.     if (sp->s_efd != -1)
  327.         (void)_close(sp->s_efd);
  328.     LISTDELETE(sp, s_link, s_rlink);
  329.     LISTPUTBEFORE(slfree, sp, s_link, s_rlink);
  330.     return 0;
  331. }
  332.  
  333.  
  334. pl_startup(num, hostlist)
  335.     int num;
  336.     struct hst **hostlist;
  337. {
  338.     int nxth = 0;                        /* next host in list to start */
  339.     struct slot *slact = 0;                /* active list of slots */
  340.     struct hst *hp;
  341.     struct slot *sp, *sp2;
  342.     struct timeval tnow;
  343.     struct timeval tout;
  344.     struct fd_set rfds;
  345.     int nfds;
  346.     int i;
  347.     int n;
  348.     char *p;
  349.     char ebuf[256];                        /* for reading stderr */
  350.  
  351.     /* init slot free list */
  352.  
  353.     slfree = &slots[RSHNPLL+1];
  354.     slfree->s_link = slfree->s_rlink = slfree;
  355.     slact = &slots[RSHNPLL];
  356.     slact->s_link = slact->s_rlink = slact;
  357.     for (i = RSHNPLL; i-- > 0; ) {
  358.         LISTPUTAFTER(slfree, &slots[i], s_link, s_rlink);
  359.     }
  360.  
  361.     /*
  362.     * keep at this until all hosts in table are completed
  363.     */
  364.  
  365.     for (; ; ) {
  366.  
  367.         /*
  368.         * if empty slots, start on new hosts
  369.         */
  370.  
  371.         for (; ; ) {
  372.  
  373.             /* find a host for slot */
  374.  
  375.             if (slfree->s_link != slfree && nxth < num)
  376.                 hp = hostlist[nxth++];
  377.             else
  378.                 break;
  379.  
  380.             sp = slfree->s_link;
  381.             LISTDELETE(sp, s_link, s_rlink);
  382.             sp->s_hst = hp;
  383.             sp->s_len = 0;
  384.             if (debugmask) {
  385.                 fprintf(stderr, "pl_startup() trying %s\n", hp->h_name);
  386.             }
  387.             phase1(sp);
  388.             if (hp->h_result) {
  389.                 /* error or fully started (manual startup) */
  390.  
  391.                 LISTPUTBEFORE(slfree, sp, s_link, s_rlink);
  392.  
  393.             } else {
  394.                 /* partially started */
  395.  
  396.                 LISTPUTBEFORE(slact, sp, s_link, s_rlink);
  397.                 gettimeofday(&sp->s_bail, (struct timezone*)0);
  398.                 tout.tv_sec = RSHTIMEOUT;
  399.                 tout.tv_usec = 0;
  400.                 TVXADDY(&sp->s_bail, &sp->s_bail, &tout);
  401.             }
  402.         }
  403.  
  404.         /* if no hosts in progress, we are finished */
  405.  
  406.         if (slact->s_link == slact)
  407.             break;
  408.  
  409.         /*
  410.         * until next timeout, get output from any slot
  411.         */
  412.  
  413.         FD_ZERO(&rfds);
  414.         nfds = 0;
  415.         TVCLEAR(&tout);
  416.         gettimeofday(&tnow, (struct timezone*)0);
  417.         for (sp = slact->s_link; sp != slact; sp = sp->s_link) {
  418.             if (TVXLTY(&sp->s_bail, &tnow)) {
  419.                 fprintf(stderr, "pl_startup() %s timed out after %d secs\n",
  420.                         sp->s_hst->h_name, RSHTIMEOUT);
  421.                 sp->s_hst->h_result = STRALLOC("PvmCantStart");
  422.                 sp2 = sp->s_rlink;
  423.                 close_slot(sp);
  424.                 sp = sp2;
  425.                 continue;
  426.             }
  427.  
  428.             if (!TVISSET(&tout) || TVXLTY(&sp->s_bail, &tout))
  429.                 tout = sp->s_bail;
  430.             if (sp->s_rfd >= 0)
  431.                 FD_SET(sp->s_rfd, &rfds);
  432.             if (sp->s_rfd > nfds)
  433.                 nfds = sp->s_rfd;
  434.             if (sp->s_efd >= 0)
  435.                 FD_SET(sp->s_efd, &rfds);
  436.             if (sp->s_efd > nfds)
  437.                 nfds = sp->s_efd;
  438.         }
  439.  
  440.         if (slact->s_link == slact)
  441.             break;
  442.  
  443.         nfds++;
  444.  
  445.         if (TVXLTY(&tnow, &tout)) {
  446.             TVXSUBY(&tout, &tout, &tnow);
  447.         } else {
  448.             TVCLEAR(&tout);
  449.         }
  450.         if (debugmask) {
  451.             fprintf(stderr, "pl_startup() select timeout is %d.%06d\n",
  452.                     tout.tv_sec, tout.tv_usec);
  453.         }
  454.         if ((n = select(nfds, &rfds, (fd_set*)0, (fd_set*)0, &tout)) == -1) {
  455.             if (errno != EINTR) {
  456.                 pvmlogperror("work() select");
  457.                 pvmbailout(0);
  458.             } 
  459.         }
  460.         if (debugmask) {
  461.             (void)fprintf(stderr, "pl_startup() select returns %d\n", n);
  462.         }
  463.         if (n < 1) {
  464.             if (n == -1 && errno != EINTR) {
  465.                 pvmlogperror("pl_startup() select");
  466.                 pvmbailout(0);    /* XXX this is too harsh */
  467.             }
  468.             continue;
  469.         }
  470.  
  471.         /*
  472.         * check for response on stdout or stderr of any slave.
  473.         */
  474.  
  475.         for (sp = slact->s_link; sp != slact; sp = sp->s_link) {
  476.  
  477.             /*
  478.             * stdout ready.  get complete line then scan config info from it.
  479.             */
  480.             if (sp->s_rfd >= 0 && FD_ISSET(sp->s_rfd, &rfds)) {
  481.                 n = win32_read_socket(sp->s_rfd, sp->s_buf + sp->s_len,
  482.                         sizeof(sp->s_buf) - sp->s_len);
  483.                 if (n > 0) {
  484.                     sp->s_len += n;
  485.                     if (sp->s_len >= sizeof(sp->s_buf)) {
  486.                         fprintf(stderr, "pl_startup() pvmd@%s: big read\n",
  487.                                 sp->s_hst->h_name);
  488.                         sp->s_hst->h_result = STRALLOC("PvmCantStart");
  489.                     }
  490.                     sp->s_buf[sp->s_len] = 0;
  491.                     if (p = CINDEX(sp->s_buf + sp->s_len - n, '\n')) {
  492.                         if (debugmask) {
  493.                             fprintf(stderr, "pvmd@%s: %s",
  494.                                     sp->s_hst->h_name, sp->s_buf);
  495.                         }
  496.                         *p = 0;
  497.                         sp->s_hst->h_result = STRALLOC(sp->s_buf);
  498.                     }
  499.  
  500.                 } else {
  501.                     if (n) {
  502.                         fprintf(stderr, "pl_startup() pvmd@%s\n",
  503.                                 sp->s_hst->h_name);
  504.                         perror("");
  505.                     } else {
  506.                         fprintf(stderr, "pl_startup() pvmd@%s: EOF\n",
  507.                                 sp->s_hst->h_name);
  508.                     }
  509.                     sp->s_hst->h_result = STRALLOC("PvmCantStart");
  510.                 }
  511.                 if (sp->s_hst->h_result) {
  512.                     sp2 = sp->s_rlink;
  513.                     close_slot(sp);
  514.                     sp = sp2;
  515.                     continue;
  516.                 }
  517.             }
  518.  
  519.             /*
  520.             * response on stderr.  log prefixed by remote's host name.
  521.             */
  522.             if (sp->s_efd >= 0 && FD_ISSET(sp->s_efd, &rfds)) {
  523.                 if ((n = win32_read_socket(sp->s_efd, ebuf, sizeof(ebuf)-1)) > 0) {
  524.                     char *p = ebuf, *q, c;
  525.  
  526.                     ebuf[n] = 0;
  527.                     fprintf(stderr, "pvmd@%s: ", sp->s_hst->h_name);
  528.                     while (c = *p++ & 0x7f) {
  529.                         if (isprint(c))
  530.                             fputc(c, stderr);
  531.  
  532.                         else {
  533.                             fputc('^', stderr);
  534.                             fputc((c + '@') & 0x7f, stderr);
  535.                         }
  536.                     }
  537.                     fputc('\n', stderr);
  538.  
  539.                 } else {
  540.                     (void)_close(sp->s_efd);
  541.                     sp->s_efd = -1;
  542.                 }
  543.             }
  544.         }
  545.     }
  546.     return 0;
  547. }
  548.  
  549.  
  550.  
  551. phase1(sp)
  552.     struct slot *sp;
  553. {
  554.     struct hst *hp;
  555.     char *hn;
  556.     char *av[16];            /* for rsh args */
  557.     int ac;
  558.     char buf[512];
  559.     char do_cmd[128];
  560.     int pid = -1;            /* pid of rsh */
  561.     char *p;
  562.     char *val=0;
  563.     FILE   *faked_stream;
  564. #ifndef NOREXEC
  565.     struct servent *se;
  566.     static u_short execport = 0;
  567.  
  568.     if (!execport) { 
  569.         if (!(se = getservbyname("exec", "tcp"))) {
  570.             fprintf(stderr, "phase1() can't getservbyname(): %s\n", "exec");
  571.             pvmbailout(0);
  572.         }
  573.         execport = se->s_port;
  574. #ifndef WIN32
  575.         endservent();
  576. #endif
  577.     }
  578. #endif
  579.  
  580.     hp = sp->s_hst;
  581.     hn = hp->h_name;
  582.     sp->s_rfd = sp->s_wfd = sp->s_efd = -1;
  583.  
  584.     /*
  585.     * XXX manual startup hack... this is if we can't use rexec or rsh
  586.     */
  587.  
  588.     if (hp->h_flag & HST_MANUAL) {
  589.         fprintf(stderr, "*** Manual startup ***\n");
  590.         fprintf(stderr, "Login to \"%s\" and type:\n", hn);
  591.         fprintf(stderr, "%s\n", hp->h_cmd);
  592.  
  593.     /* get version */
  594.  
  595.         fprintf(stderr, "Type response: ");
  596.         fflush(stderr);
  597.         if (!(fgets(buf, sizeof(buf), stdin))) {
  598.             fprintf(stderr, "host %s read error\n", hn);
  599.             goto oops;
  600.         }
  601.         p = buf + strlen(buf) - 1;
  602.         if (*p == '\n')
  603.             *p = 0;
  604.         hp->h_result = STRALLOC(buf);
  605.         fprintf(stderr, "Thanks\n");
  606.         fflush(stderr);
  607.         return 0;
  608.     }
  609.  
  610.     /*
  611.     * XXX end manual startup hack
  612.     */
  613.  
  614.     if (!(hp->h_flag & HST_PASSWORD)) {        /* use rsh to start */
  615.         int wpfd[2], rpfd[2], epfd[2];
  616.         int i;
  617.  
  618.         if (debugmask) {
  619.             fprintf(stderr, "phase1() trying rsh to %s\n", hn);
  620.         }
  621.  
  622.     /* fork an rsh to startup the slave pvmd */
  623.  
  624. #ifdef    IMA_TITN
  625.         if (socketpair(AF_UNIX, SOCK_STREAM, 0, wpfd) == -1
  626.         || socketpair(AF_UNIX, SOCK_STREAM, 0, rpfd) == -1
  627.         || socketpair(AF_UNIX, SOCK_STREAM, 0, epfd) == -1) {
  628.             pvmlogperror("phase1() socketpair");
  629.             goto oops;
  630.         }
  631. #else
  632. #ifndef WIN32
  633.         if (pipe(wpfd) == -1 || pipe(rpfd) == -1 || pipe(epfd) == -1) {
  634.             pvmlogperror("phase1() pipe");
  635.             goto oops;
  636.         }
  637. #endif
  638. #endif
  639.  
  640.         if (debugmask) {
  641.             fprintf(stderr, "phase1() pipes: %d %d %d %d %d %d\n",
  642.                     wpfd[0], wpfd[1], rpfd[0], rpfd[1], epfd[0], epfd[1]);
  643.         }
  644. #ifndef WIN32
  645.         if ((pid = fork()) == -1) {
  646.             pvmlogperror("phase1() fork");
  647.             pvmbailout(0);
  648.         }
  649.         if (!pid) {
  650.  
  651.             (void)dup2(wpfd[0], 0);
  652.             (void)dup2(rpfd[1], 1);
  653.             (void)dup2(epfd[1], 2);
  654.             for (i = getdtablesize(); --i > 2; )
  655.                 (void)close(i);
  656. #else
  657.             {
  658. #endif
  659.     
  660.         
  661.             ac = 0;
  662.             if (getenv("PVM_RSH"))                /* do we have a setting for rsh ?*/
  663.                 av[ac++] = getenv("PVM_RSH");
  664.             else 
  665.                 av[ac++] = RSHCOMMAND;
  666.             av[ac++] = hn;
  667.             if (hp->h_login) {
  668.                 av[ac++] = "-l";
  669.                 av[ac++] = hp->h_login;
  670.             }
  671.             else {
  672.                 hp->h_login=username;
  673.                 av[ac++] = "-l";
  674.                 av[ac++] = hp->h_login;
  675.             }
  676.             av[ac++] = hp->h_cmd;
  677.         //    av[ac++] = "-u";
  678.         //    av[ac++] = username;
  679.             av[ac++] = 0;
  680.             if (debugmask) {
  681.                 for (ac = 0; av[ac]; ac++)
  682.                     fprintf(stderr, "av[%d]=\"%s\" ", ac, av[ac]);
  683.                 fputc('\n', stderr);
  684.             }
  685. #ifndef WIN32
  686.             execvp(av[0], av);
  687.             fputs("phase1() execvp failed\n", stderr);
  688.             fflush(stderr);
  689.             _exit(1);
  690. #else
  691.             strcpy(do_cmd,av[0]);
  692.             for (ac = 1; av[ac]; ac++) {
  693.                     strcat(do_cmd," ");
  694.                     strcat(do_cmd,av[ac]);
  695.             }
  696.             faked_stream=_popen(do_cmd,"r"); 
  697.             
  698.             if (faked_stream != NULL)
  699.             {
  700.                 while (1) {
  701.                     fgets(buf,100,faked_stream);
  702.                     if (strstr(buf,"ddpro")) {
  703.                         if (!val)
  704.                             val = malloc(sizeof (buf) * sizeof(char));
  705.                         strcpy(val,buf);
  706.                         sp->s_hst->h_result=val;
  707.                         break;
  708.                         /* we got the message */
  709.                     }
  710.                     if (strcmp(buf,"PvmDupHost")){
  711.                         if (!val)
  712.                             val = malloc(sizeof (buf) * sizeof(char));
  713.                         strcpy(val,buf);
  714.                         sp->s_hst->h_result=val;
  715.                         break;
  716.                     }
  717.                 }
  718.             }        
  719.  
  720.             // how can we close this ???
  721.             // _pclose(faked_stream);
  722.  
  723.             
  724. #endif
  725.         }
  726. #ifndef WIN32
  727.         (void)close(wpfd[0]);
  728.         (void)close(rpfd[1]);
  729.         (void)close(epfd[1]);
  730.         sp->s_wfd = wpfd[1];
  731.         sp->s_rfd = rpfd[0];
  732.         sp->s_efd = epfd[0];
  733. #endif
  734.     } else {        /* use rexec to start */
  735.  
  736. #ifdef NOREXEC
  737.         fprintf(stderr, "slconfg() sorry, no rexec()\n");
  738.         goto oops;
  739. #else
  740.         if (debugmask) {
  741.             fprintf(stderr, "phase1() rexec \"%s\"\n", hp->h_cmd);
  742.         }
  743. #ifndef WIN32
  744.         if ((sp->s_wfd = sp->s_rfd = rexec(&hn, execport,
  745.                 (hp->h_login ? hp->h_login : username),
  746.                 (char*)0, hp->h_cmd, &sp->s_efd))
  747.         == -1) {
  748.             fprintf(stderr, "phase1() rexec failed for host %s\n", hn);
  749.             goto oops;
  750.         }
  751. #endif
  752.         sp->s_hst->h_result = malloc (512 * sizeof(char));
  753.  
  754.         if (!rexec(hn,(hp->h_login ? hp->h_login : username),
  755.                     hp->h_cmd,sp->s_hst->h_result))
  756.         {
  757.             fprintf(stderr, "phase1() rexec failed for host %s\n", hn);
  758.             goto oops;
  759.         }
  760.  
  761.  
  762. #endif
  763.     }
  764.     return 0;
  765.  
  766. oops:
  767.     hp->h_result = STRALLOC("PvmCantStart");
  768. oops2:
  769.     if (sp->s_wfd != -1)
  770.         _close(sp->s_wfd);
  771.     if (sp->s_rfd != -1)
  772.         _close(sp->s_rfd);
  773.     if (sp->s_efd != -1)
  774.         _close(sp->s_efd);
  775.     sp->s_wfd = sp->s_rfd = sp->s_efd = -1;
  776.     return 1;
  777. }
  778.  
  779.  
  780.  
  781. #endif    /*RSHNPLL > 1*/
  782.  
  783.